package cn.wit.db.config;

import cn.wit.db.security.AuthFailureHandler;
import cn.wit.db.security.AuthSuccessHandler;
import cn.wit.db.security.JwtAuthenticationFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpStatus;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
	// 处理jwt token认证的filter
	@Autowired
	private JwtAuthenticationFilter jwtAuthenticationFilter;
	
	@Autowired
    AuthSuccessHandler successHandler;
	
	@Autowired
    AuthFailureHandler failureHandler;
	
	/**
	 * 配置登陆页面、请求路径拦截规则
	 */
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.formLogin()
			.loginProcessingUrl("/login")
			.permitAll()
			.successHandler(successHandler)
			.failureHandler(failureHandler)
			// 使用jwt token机制认证，不需要开启session
		.and()
			.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
		.and()
			.authorizeRequests()	// 开始配置请求认证规则
			.antMatchers("/").permitAll()
			.antMatchers("/index.html").permitAll()
			.antMatchers("/css/**").permitAll()
			.antMatchers("/js/**").permitAll()
			.antMatchers("/font/**").permitAll()
			.antMatchers("/favicon.ico").permitAll()
			.antMatchers("/img/**").permitAll()
			.anyRequest()
			.authenticated()		// 所有请求都需要认证
		.and()
			// 未登陆、请求没有带token、或者token过期
			.exceptionHandling().authenticationEntryPoint(
				(request, response, e) -> {
					response.sendError(HttpStatus.UNAUTHORIZED.value(), e.getMessage());
				}
			)
		.and()
			.cors()			// 防止/login请求报cors错误
		.and()
			.csrf().disable();

		http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
	}
	
	@Bean
	public BCryptPasswordEncoder configPasswordEncoder() {
		return new BCryptPasswordEncoder();
	}
}
